package com.example.mysql.druid;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;

//@Configuration
//@PropertySource(value = "classpath:druid.properties")
public class DruidConfig
{
    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;
    /**
     * 最大连接池数量
     */
    @Value("${druid.maxActive}")
    private int maxActive;
    /**
     * 初始化时建立物理连接的个数。初始化发生在显示调用init方法，或者第一次getConnection时
     */
    @Value("${druid.initialSize}")
    private int initialSize;
    /**
     * 获取连接时最大等待时间，单位毫秒。
     * 配置了maxWait之后，缺省启用公平锁，并发效率会有所下降
     * 如果需要可以通过配置useUnfairLock属性为true使用非公平锁
     */
    @Value("${druid.maxWait}")
    private int maxWait = 60000;
    /**
     * 最小连接池数量
     */
    @Value("${druid.minIdle}")
    private int minIdle = 1;
    /**
     * 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
     */
    @Value("${druid.timeBetweenEvictionRunsMillis}")
    private long timeBetweenEvictionRunsMillis = 60000;
    /**
     * 配置一个连接在池中最小生存的时间，单位是毫秒
     */
    @Value("${druid.minEvictableIdleTimeMillis}")
    private long minEvictableIdleTimeMillis = 600000;
    /**
     * 配置一个连接在池中最大生存的时间，单位是毫秒
     */
    @Value("${druid.maxEvictableIdleTimeMillis}")
    private long maxEvictableIdleTimeMillis = 900000;
    /**
     * 用来检测连接是否有效的sql，要求是一个查询语句，常用select 'x'。
     * 如果validationQuery为null，testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
     */
    @Value("${druid.validationQuery}")
    private String validationQuery = "select 1";
//    /**
//     * 单位：秒，检测连接是否有效的超时时间。
//     * 底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法
//     */
//    private int validationQueryTimeout;
    /**
     * 建议配置为true，不影响性能，并且保证安全性。
     * 申请连接的时候检测，如果空闲时间大于timeBetweenEvictionRunsMillis，执行validationQuery检测连接是否有效。
     */
    @Value("${druid.testWhileIdle}")
    private boolean testWhileIdle = true;
    /**
     * 申请连接时执行validationQuery检测连接是否有效，做了这个配置会降低性能。
     */
    @Value("${druid.testOnBorrow}")
    private boolean testOnBorrow = false;
    /**
     * 归还连接时执行validationQuery检测连接是否有效，做了这个配置会降低性能。
     */
    @Value("${druid.testOnReturn}")
    private boolean testOnReturn = false;
    /**
     * 连接池中的minIdle数量以内的连接，空闲时间超过minEvictableIdleTimeMillis，则会执行keepAlive操作。
     */
    @Value("${druid.keepAlive}")
    private boolean keepAlive = true;
    @Value("${druid.filters}")
    private String filters = "stat";
    @Value("${druid.asyncInit}")
    private boolean asyncInit = true;
    @Value("${druid.stat.mergeSql}")
    private String statMergeSql = "true";
    @Value("${druid.stat.slowSqlMillis}")
    private String slowSqlMillis = "50000";
    @Value("${druid.useGlobalDataSourceStat}")
    private String useGlobalDataSourceStat;

    @Bean
    public DataSource dataSource()
    {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setMaxActive(20);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setMaxActive(maxActive);
        dataSource.setMaxWait(maxWait);
        dataSource.setMinIdle(minIdle);
        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        dataSource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
        dataSource.setValidationQuery(validationQuery);
//        dataSource.setValidationQueryTimeout(validationQueryTimeout);
        dataSource.setTestWhileIdle(testWhileIdle);
        dataSource.setTestOnBorrow(testOnBorrow);
        dataSource.setTestOnReturn(testOnReturn);
        dataSource.setKeepAlive(keepAlive);
        try
        {
            dataSource.setFilters(filters);
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        dataSource.setAsyncInit(asyncInit);
        Properties properties = new Properties();
        properties.setProperty("druid.stat.mergeSql", statMergeSql);
        properties.setProperty("druid.stat.slowSqlMillis", slowSqlMillis);
        dataSource.setConnectProperties(properties);
        return dataSource;
    }
}
